<?php
	/**
	  * @package	MyDebuger
	  * @name		MyLoader
	  * @brief		Clase para cargar ficheros de clases PHP
	  * @author		Hermann D. Schimpf <hschimpf@gschimpf.com>
	  * @license	http://opensource.org/licenses/gpl-2.0.php
	  * @date		2009-12-11
	  * @version	0.1.0
  	**/

	final class MyLoader extends MyDebuger implements MyVersions {
		/* version de la clase */
		private static $version			= 0;
		/* subversion de la clase */
		private static $subversion		= 1;
		/* numero de revision de la clase */
		private static $revision		= 0;

		/* nombre de las clases y direccion a sus ficheros */
		private $fileClasses			= Array();
		/* fichero de configuraciones */
		private $configFile			= 'classes.config';
		/* expresion para validar el formato del ficher */
		private $configFileFormat	= '';
		/* bandera para saber si se cargaron los datos */
		private $datosCargados		= False;

		public function __construct($debug = False) {
			/* creamos el padre */
			parent::__construct($debug, __CLASS__, 086);
			/* habilitamos el registro en un fichero */
			$this->enableLog(__CLASS__ . '.log');
			/* cargamos los datos */
			$this->loadDataFromFile();
		}

		public static final function getVersion() {
			/* retornamos la version actual de la clase */
			return 'v' . self::$version . '.' . self::$subversion . '.' . self::$revision;
		}

		private function loadDataFromFile() {
			try {
				try {
					/* verificamos el archivo */
					$this->verificarFichero();
					/* cargamos los datos del fichero */
					$this->cargarDatosFichero();
					/* modificamos la bandera */
					$this->datosCargados = True;
				} catch (Exception $e) {
					/* capturamos todos los errores y los transformamos en mi excepcion */
					$this->convertToMyException($e);
				}
			} catch (MyException $e) {
				/* si se produjo una excepcion la manejamos con el metodo 'show' */
				$this->show($e->getMensaje());
			}
		}

		private function verificarFichero() {
			/* mostramos un mensaje */
			$this->show('Verificando fichero de configuraciones..', False);
			/* verificamos si el fichero existe */
			if (!file_exists($this->configFile))
				/* salimos con una excepcion */
				$this->newException('El fichero ' . $this->italic($this->configFile) . ' no existe');
			/* verificamos si podemos leer el fichero */
			if (!is_readable($this->configFile))
				/* salimos con una excepcion */
				$this->newException('No se tienen permisos de lectura sobre el fichero ' . $this->italic($this->configFile));
			/* mostramos ok al mensaje */
			$this->showOK();
		}

		private function cargarDatosFichero() {
			/* mostramos un mensaje */
			$this->show('Cargando configuraciones desde el fichero ' . $this->italic($this->configFile) . '..', False);
			/* abrimos el fichero */
			$this->abrirFichero();
			/* verificamos que el fichero tenga el formato correcto */
			$this->verificarFormatoFichero();
			/* limpiamos el fichero */
			$this->limpiarFichero();
			/* procesamos el fichero */
			$this->procesarFichero();
			/* mostramos ok al mensaje */
			$this->showOK();
		}

		private function abrirFichero() {
			/* obtenemos los datos del fichero */
			$this->configFile = file_get_contents($this->configFile);
		}

		private function verificarFormatoFichero() {
			/* verificamos que los datos del fichero sean correctos */
			if (!preg_match($this->configFileFormat, $this->configFile))
				/* salimos con una excepcion */
				$this->newException('El formato del fichero no es correcto');
		}

		private function limpiarFichero() {
			/* ingresamos a un buqle */
			foreach (Array(
				/* reemplazamos los saltos a un solo tipo */
				"\r"		=> "\n",
				/* eliminamos saltos repetidos */
				"\n\n"	=> "\n",
				/* eliminamos los espacios en blanco */
				' '		=> '',
				/* eliminamos los tabuladores */
				"\t"		=> ''
			) AS $busca => $reemplaza) {
				/* buscamos la cadena repetida */
				while (strstr($this->configFile, $busca))
					/* reemplazamos los saltos dobles */
					str_replace($busca, $reemplaza, $this->configFile);
			}
		}

		private function procesarFichero() {
			/* recorremos cada linea del archivo */
			foreach (explode("\n", $this->configFile) AS $classFile) {
				/* separamos el nombre de la clase y la ruta al fichero */
				$datos = explode('=>', $classFile);
				/* procesamos el fichero-clase */
				$this->procesarClase($datos[0], $datos[1]);
			}
		}

		private function procesarClase($class, $fileName) {
			/* realizamos verificaciones del fichero */
			$this->verificarFicheroClase($fileName);
			/* verificamos si la clase existe en el fichero */
			$this->verificarClaseEnFichero($class, $fileName);
			/* almacenamos el nombre de la clase y el fichero */
			$this->guardarClaseFichero($class, $fileName);
		}

		private function verificarFicheroClase($fileName) {
			/* verificamos si el fichero existe */
			if (!file_exists($fileName))
				/* salimos con una excepcion */
				$this->newException('El fichero ' . $this->italic($fileName) . ' no existe');
			/* verificamos si podemos leer el fichero */
			if (!is_readable($fileName))
				/* salimos con una excepcion */
				$this->newException('No se tienen permisos de lectura sobre el fichero ' . $this->italic($fileName));
		}

		private function verificarClaseEnFichero($class, $fileName) {
			/* verificamos si la clase esta definida en el fichero */
			if (!strstr(file_get_contents($fileName), $class))
				/* salimos con una excepcion */
				$this->newException('La clase ' . $this->italic($this->bold($class)) . ' no esta definida en el fichero ' . $this->italic($fileName));
		}

		private function guardarClaseFichero($class, $fileName) {
			/* agregamos un elemento al array con las clases */
			$this->fileClasses[$class] = $fileName;
		}
	}
?>
